/*
 * Copyright 2009 BioTeam Inc
 * 
 * Licensed under License GNU LESSER GENERAL PUBLIC LICENSE version 3.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.gnu.org/copyleft/lesser.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package net.bioteam.appweb.gwt.apps.client.login;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import net.bioteam.appweb.gwt.apps.client.LoginHolder;
import net.bioteam.appweb.gwt.apps.client.StaticHolder;
import net.bioteam.appweb.gwt.apps.client.Util.LinkLabel;
import net.bioteam.appweb.gwt.apps.client.Util.Util;
import net.bioteam.appweb.gwt.apps.clientandserver.LoginProxy;
import net.bioteam.appweb.gwt.apps.clientandserver.LoginProxyAsync;
import net.bioteam.common.user.User;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.FormErrorOrientation;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.HTMLFlow;
import com.smartgwt.client.widgets.IButton;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.validator.CustomValidator;
import com.smartgwt.client.widgets.form.validator.LengthRangeValidator;
import com.smartgwt.client.widgets.form.validator.RegExpValidator;
import com.smartgwt.client.widgets.form.validator.Validator;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;

public class LoginPanel extends VLayout
{

	public Label messageLabel;
	public static final int leftWidth=250;
	
	public Canvas loginCanvas;
	
	Canvas loginWin;
	Canvas registerWin;
	Canvas retrieveWin;
	
	Canvas visibleWin;
	
	
	public void toRegister()
	{
		switchPanel(registerWin);
	}
	
	public void toRetrieve()
	{
		switchPanel(retrieveWin);
	}
	
	public void toLogin()
	{
		switchPanel(loginWin);
	}
	public void switchPanel(Canvas newChild)
	{
		if (visibleWin!=null)
		{
			visibleWin.hide();
		}
		newChild.show();
		visibleWin=newChild;
	}
	
	public LoginPanel()
	{
		setHeight100();
		setWidth100();
		
		//-----------------
		HTMLFlow top = new HTMLFlow();
		top.setAutoHeight();
		top.setContentsURL("loginheader.html");
		top.setStyleName("myhead");
		//top.setBackgroundColor("yellow");
		top.setWidth100();
		top.setBorder("2px solid gray");
		addMember(top);
		
		HLayout middle=new HLayout();
		middle.setWidth100();
	
		
		loginCanvas=new Canvas();
		loginCanvas.setWidth(leftWidth);
		loginCanvas.setHeight100();
		
		loginWin=getLogin();
		loginWin.setVisible(true);
		loginCanvas.addChild(loginWin);
		visibleWin=loginWin;
		
		registerWin=getRegister();
		registerWin.setVisible(false);
		loginCanvas.addChild(registerWin);
		
		
		retrieveWin=getRetrieve();
		retrieveWin.setVisible(false);
		loginCanvas.addChild(retrieveWin);
		
		
		middle.addMember(loginCanvas);
		
		// --------------center content
		HTMLFlow content = new HTMLFlow();
		content.setHeight100();
		content.setWidth("*");
		content.setContentsURL("features.html");
		middle.addMember(content);
		
		addMember(middle);
		
		// --------------footer
		HTMLFlow footer = new HTMLFlow();
		footer.setAutoHeight();
		footer.setBorder("2px solid gray");
		footer.setStyleName("myfooter");
		footer.setContentsURL("loginfooter.html");
		addMember(footer);
	}
	
	
	public Canvas getLogin()
	{
		
		
		
		messageLabel=new Label();
		//messageLabel.setStyleName("red");
		messageLabel.setHeight(40);
		messageLabel.setWidth100();
		messageLabel.setAlign(Alignment.LEFT);
		
		
		final DynamicForm loginForm = new DynamicForm();
		loginForm.setWidth(250);
		loginForm.setCellBorder(1);
		

		final TextItem usernameItem = new TextItem("username");
		usernameItem.setTitle("Username");
		usernameItem.setRequired(true);
		usernameItem.setDefaultValue("");
		usernameItem.setShowErrorText(true);

		final TextItem passwordItem = new TextItem("password");
		passwordItem.setTitle("Password");
		passwordItem.setRequired(true);
		passwordItem.setType("password");
		passwordItem.setShowErrorText(true);

		loginForm.setFields(usernameItem, passwordItem);
		// loginform will be in the middle instead of left.
		loginForm.setLayoutAlign(Alignment.LEFT);

		
		IButton b=new IButton("Login");
		b.setWidth(50);
		b.addClickHandler(new ClickHandler(){

			public void onClick(ClickEvent event)
			{
				if (loginForm.validate())
				{
					Map<String, String> values=new HashMap<String, String>();
					
					//User user=new User();
					values.put("username", usernameItem.getValue().toString());
					
					values.put("password", LoginHolder.hashPassword(usernameItem.getValue().toString(), passwordItem.getValue().toString()));
					//values.put("password", passwordItem.getValue().toString());
					LoginProxyAsync login=LoginProxy.Util.getInstance();
					login.login(values, new AsyncCallback<User>(){

						public void onFailure(Throwable caught)
						{
							StaticHolder.setMessage(messageLabel, caught.getMessage(), 4);
						}

						public void onSuccess(User result)
						{
							StaticHolder.user=result;
							StaticHolder.loginPanel.loginPanel.hide();
							StaticHolder.mainPanel.init();
							StaticHolder.mainPanel.show();
							
							
							Date rightnow=new Date();
							//give the end user two days. Session will be out after this definitely.
							rightnow.setTime(rightnow.getTime()+24*3600*1000);
							Cookies.setCookie("_username", result.getName());
							
							if (History.getToken()==null || History.getToken().length()==0)
							{
								History.newItem(result.getPassword());
							} else
							{
								History.fireCurrentHistoryState();
							}
						}
						
					});
				}
			}
		});
			
		
		HLayout ts1=new HLayout();
		ts1.setWidth(50);
		ts1.setHeight(30);
		ts1.addMember(b);
		ts1.setLayoutAlign(Alignment.CENTER);
		
		
		
		LinkLabel r=new LinkLabel("Register");
		r.setWidth(60);
		r.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event)
			{
				toRegister();
			}});
		
		LinkLabel f=new LinkLabel("Forget Username/Password?");
		f.setWidth(180);
		f.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event)
			{
				toRetrieve();
			}});
		//ToolStrip ts=new ToolStrip();
		HLayout ts=new HLayout();
		ts.setWidth(240);
		
		ts.setHeight(30);
		//ts.setAlign(Alignment);
		ts.setLayoutAlign(Alignment.LEFT);
		ts.setShowEdges(false);
		ts.addMember(r);
		ts.addMember(f);
		
		VLayout contentPanel=new VLayout();
		contentPanel.setBorder("2px solid gray");
		contentPanel.setWidth(leftWidth);
		contentPanel.setHeight100();
		contentPanel.addMember(loginForm);
		contentPanel.addMember(ts1);
		contentPanel.addMember(ts);
		
		return contentPanel;
		
	}
	
	
	public Canvas getRegister()
	{
		final Label messageLabel=new Label();
		messageLabel.setStyleName("red");
		messageLabel.setHeight(40);
		messageLabel.setWidth100();
		messageLabel.setAlign(Alignment.LEFT);
		
		final DynamicForm form = new DynamicForm();
		form.setWidth(250);
		// form.setBorder("2px solid red");
		
		//form.setWidth100();
		form.setHeight(150);
		form.setOverflow(Overflow.AUTO);
		//form.setColWidths(150, 100);
		form.setCellBorder(1);
		form.setNumCols(2);

		form.setShowInlineErrors(true);
		form.setShowErrorText(true);
		form.setErrorOrientation(FormErrorOrientation.TOP);
		form.setRequiredTitleSuffix("<em style='color:red;'>***</em>");
		//form.setBackgroundColor("white");
		
		TextItem email = new TextItem("email");
		email.setTitle("Your email ");
		email.setRequired(true);
		RegExpValidator regV=new RegExpValidator();
		regV.setExpression(".+@.+");
		regV.setErrorMessage("invalid email address");
		email.setValidators(regV);
		
		TextItem username=new TextItem("username");
		username.setRequired(true);
		Validator validator=new CustomValidator()
		{

			@Override
			protected boolean condition(Object value)
			{
				if (value==null)
					return false;
				String str=value.toString();
				if (str.length()<6)
				{
					setErrorMessage("must have 6 characters at minimal");
					return false;
				}
				if (!str.matches("^[a-zA-Z].+"))
				{
					setErrorMessage("First character has to be a letter");
					return false;
				}
				if (!str.matches("(\\w|\\d)+"))
				{
					setErrorMessage("all characters have to be letter or number");
					return false;
				}
				return true;
			}
		};
		username.setValidators(validator);
		
		
		TextItem password = new TextItem("password");
		password.setRequired(true);
		LengthRangeValidator lrv=new LengthRangeValidator();
		lrv.setMin(new Integer(6));
		password.setValidators(lrv);
				
		form.setItems(email, username, password);
		form.setLayoutAlign(Alignment.LEFT);

		IButton r=new IButton("Register");
		r.setWidth(80);
		r.addClickHandler(new ClickHandler(){

			public void onClick(ClickEvent event)
			{
				if (!form.validate())
				{
					return;
				}
				AsyncCallback callback = new AsyncCallback()
				{

					public void onFailure(Throwable caught)
					{
						StaticHolder.setMessage(messageLabel, caught.getMessage(), 6);
					}

					public void onSuccess(Object result)
					{

						String message="Email is sent to you for verrification. You are ready to login in";
						StaticHolder.setMessage(StaticHolder.loginPanel.loginPanel.messageLabel, message,  10);
						toLogin();
						
					}
				};
				String email=form.getValueAsString("email");
				String username=form.getValueAsString("username");
				String password=form.getValueAsString("password");
				String hash=Util.mymd5(email+"_"+username);
				
				Map<String, String> values=new HashMap<String, String>();
				values.put("email", email);
				values.put("username", username);
				values.put("password", password);
				values.put("hash", hash);
				LoginProxyAsync login=LoginProxy.Util.getInstance();
				login.register(values, callback);
				
			}});
		
		
		Label l=new LinkLabel("to Login");
		l.setWidth(70);
		l.addClickHandler(new ClickHandler(){

			public void onClick(ClickEvent event)
			{
				toLogin();
				
			}});
		
		HLayout ts=new HLayout();
		ts.setWidth(80);
		//ts.setBackgroundColor("yellow");
		ts.setLayoutAlign(Alignment.CENTER);
		ts.setHeight(30);
		ts.addMember(r);
		ts.addMember(l);
		
		VLayout contentPanel=new VLayout();
		contentPanel.setBorder("2px solid gray");
		contentPanel.setWidth(leftWidth);
		contentPanel.setHeight100();
		
		contentPanel.addMember(messageLabel);
		contentPanel.addMember(form);
		contentPanel.addMember(ts);
		
		return contentPanel;
	}
	
	public Canvas getRetrieve()
	{
		final Label messageLabel=new Label();
		messageLabel.setStyleName("red");
		messageLabel.setHeight(40);
		messageLabel.setWidth100();
		messageLabel.setAlign(Alignment.LEFT);
		
		final DynamicForm form = new DynamicForm();
		// form.setBorder("2px solid red");
		
		form.setWidth(250);
		form.setHeight(80);
		form.setOverflow(Overflow.AUTO);
		//form.setColWidths(150, 100);
		form.setCellBorder(1);
		form.setNumCols(2);

		form.setShowInlineErrors(true);
		form.setShowErrorText(true);
		form.setErrorOrientation(FormErrorOrientation.TOP);
		form.setRequiredTitleSuffix("<em style='color:red;'>***</em>");
		//form.setBackgroundColor("white");
		
		TextItem email = new TextItem("email");
		email.setTitle("Your email");
		email.setRequired(true);
		RegExpValidator regV=new RegExpValidator();
		regV.setExpression(".+@.+");
		regV.setErrorMessage("invalid email address");
		email.setValidators(regV);
		
		
		
		form.setItems(email);
		form.setLayoutAlign(Alignment.LEFT);

		
		
		IButton r=new IButton("Retrieve");
		r.setWidth(80);
		r.addClickHandler(new ClickHandler(){

			public void onClick(ClickEvent event)
			{
				if (!form.validate())
				{
					return;
				}
				AsyncCallback callback = new AsyncCallback()
				{

					public void onFailure(Throwable caught)
					{
						StaticHolder.setMessage(messageLabel, caught.getMessage(), 6);
					}

					public void onSuccess(Object u)
					{
						
						String message="Account is sent to your email address";
						StaticHolder.setMessage(StaticHolder.loginPanel.loginPanel.messageLabel, message,  10);
						toLogin();
					}
				};
				String email=form.getValueAsString("email");
				
				String hash=Util.mymd5(email+"_bin");
			
				LoginProxyAsync login=LoginProxy.Util.getInstance();
				login.retrieve(email, hash, callback);
				
			}});
		
		
		
		Label l=new LinkLabel("to Login");
		l.setWidth(80);
		l.addClickHandler(new ClickHandler(){

			public void onClick(ClickEvent event)
			{
				toLogin();
				
			}});
		HLayout ts=new HLayout();
		ts.setWidth(80);
		//ts.setBackgroundColor("yellow");
		ts.setLayoutAlign(Alignment.CENTER);
		ts.setHeight(30);
		ts.addMember(r);
		ts.addMember(l);
		
		VLayout contentPanel=new VLayout();
		contentPanel.setBorder("2px solid gray");
		contentPanel.setWidth(leftWidth);
		contentPanel.setHeight100();
		
		contentPanel.addMember(messageLabel);
		contentPanel.addMember(form);
		contentPanel.addMember(ts);
		
		return contentPanel;
	}

}
